extends ../layout

block style

block content
  h1 promise 实现
  p 下面是一个简单的 promise 雏形
  pre
    |function Promise(fn) {
    |  var value = null,
    |    callbacks = []; // 回调函数数组
    |
    |  this.then = function (onFufilled) {
    |    callbacks.push(onFufilled);
    |  }
    |
    |  function resolve(value) {
    |    callbacks.forEach(function (callback) {
    |      callback(value);
    |    })
    |  }
    |
    |  fn(resolve);
    |}
  p 加入 链式then、延时机制、promise状态
  pre
    |function Promise(fn) {
    |  var value = null,
    |    state = 'pending',
    |    callbacks = []; // 回调函数数组
    |
    |  this.then = function (onFufilled) {
    |    if(state === 'pending') {
    |      callbacks.push(onFufilled);
    |      return this;
    |    }
    |    onFufilled(value);
    |    return this;
    |  }
    |
    |  function resolve(newValue) {
    |    value = newValue;
    |    state = 'fulfilled';
    |    setTimeout(function() {
    |      callbacks.forEach(function (callback) {
    |        callback(value);
    |      })
    |    }, 0);
    |  }
    |
    |  fn(resolve);
    |}
  p 处理 串行链式Promise
  pre
    |function Promise(fn) {
    |  var value = null,
    |    state = 'pending',
    |    callbacks = []; // 回调函数数组
    |
    |  this.then = function (onFufilled) {
    |    return new Promise(function (resolve) {
    |      handle({
    |        onFufilled: onFufilled || null,
    |        resolve: resolve
    |      })
    |    })
    |  }
    |
    |  function handle (callback) {
    |    if(state === 'pending') {
    |      callbacks.push(callback);
    |      return;
    |    }
    |    // 如果 then 没有注册任何函数
    |    if(!callback.onFufilled) {
    |      callback.resolve(value);
    |      return;
    |    }
    |    var ret = callback.onFufilled(value);
    |    callback.resolve(ret);
    |  }
    |
    |  function resolve(newValue) {
    |    if(newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
    |      var then = newValue.then;
    |      if(typeof then === 'function') {
    |        then.call(newValue, resolve);
    |        return;
    |      }
    |    }
    |    value = newValue;
    |    state = 'fulfilled';
    |    setTimeout(function() {
    |      callbacks.forEach(function (callback) {
    |        handle(callback);
    |      })
    |    }, 0);
    |  }
    |
    |  fn(resolve);
    |}
  p 加入 错误处理 较为完整的版本
  pre
    |function Promise(fn) {
    |  var value = null,
    |    state = 'pending',
    |    callbacks = []; // 回调函数数组
    |
    |  this.then = function (onFufilled, onRejected) {
    |    return new Promise(function (resolve) {
    |      handle({
    |        onFufilled: onFufilled || null,
    |        onRejected: onRejected || null,
    |        resolve: resolve,
    |        reject: reject
    |      })
    |    })
    |  }
    |
    |  function handle (callback) {
    |    if(state === 'pending') {
    |      callbacks.push(callback);
    |      return;
    |    }
    |    var cb = state === 'fulfilled' ? callback.onFufilled : callback.onRejected,
    |      ret;
    |    if(cb === null) {
    |      cb = state === 'fulfilled' ? callback.resolve : callback.reject;
    |      cb(value);
    |      return;
    |    }
    |    ret = cb(value);
    |    callback.resolve(ret);
    |  }
    |
    |  function reject (reason) {
    |    state = 'rejected';
    |    value = reason;
    |    execute();
    |  }
    |  function execute() {
    |    setTimeout(function () {
    |      callbacks.forEach(function (callback) {
    |        handle(callback);
    |      }, 0);
    |    })
    |  }
    |
    |  function resolve(newValue) {
    |    if(newValue && (typeof newValue === 'object' || typeof newValue === 'function')) {
    |      var then = newValue.then;
    |      if(typeof then === 'function') {
    |        then.call(newValue, resolve, reject);
    |        return;
    |      }
    |    }
    |    value = newValue;
    |    state = 'fulfilled';
    |    setTimeout(function() {
    |      callbacks.forEach(function (callback) {
    |        handle(callback);
    |      })
    |    }, 0);
    |  }
    |
    |  fn(resolve, reject);
    |}
  script(src="/javascripts/promise/promise.js")